/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.jena.rdfs;

import static org.apache.jena.rdfs.LibTestRDFS.findInGraph;
import static org.apache.jena.rdfs.LibTestRDFS.node;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.PrintStream;
import java.util.List;

import org.junit.jupiter.api.Test;

import org.apache.jena.atlas.lib.ListUtils;
import org.apache.jena.graph.Graph;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.Triple;
import org.apache.jena.rdfs.engine.ConstRDFS;
import org.apache.jena.rdfs.setup.MatchVocabRDFS;
import org.apache.jena.riot.RDFDataMgr;

/** Test the setup matcher that provides access to a setup as a (s,p,o) access */
public class TestMatchVocab {
    static final String DIR = "testing/RDFS";

    //static final String DATA_FILE = DIR+"/rdfs-data.ttl";
    static final String VOCAB_FILE = DIR+"/rdfs-vocab.ttl";
    private static final String RULES_FILE_BWD = DIR+"/rdfs-min-backwards.rules";
    // Forward rules.
    private static final String RULES_FILE_FWD = DIR+"/rdfs-min.rules";

    private static final String RULES_FILE = RULES_FILE_FWD;

    private static Graph referenceGraph;
    protected static Graph vocab;
    protected static MatchVocabRDFS matchVocab;
    protected static SetupRDFS setup;

    static {
        vocab = RDFDataMgr.loadGraph(VOCAB_FILE);
        referenceGraph = LibTestRDFS.createRulesGraph(vocab, vocab, RULES_FILE);
        setup = new SetupRDFS(vocab);
        matchVocab = new MatchVocabRDFS(setup);
    }

    @Test public void matchVocab_01() { test(node("T"), ConstRDFS.rdfsSubClassOf, null); }
    @Test public void matchVocab_02() { test(null, ConstRDFS.rdfsSubClassOf, null); }
    @Test public void matchVocab_03() { test(null, ConstRDFS.rdfsSubClassOf, node("T2")); }
    @Test public void matchVocab_04() { test(node("T"), ConstRDFS.rdfsSubClassOf, null); }
    @Test public void matchVocab_05() { test(node("T"), ConstRDFS.rdfsSubClassOf, node("T")); }

    @Test public void matchVocab_10() { test(node("T"), null, null); }
    @Test public void matchVocab_11() { test(null, null, node("T2")); }
    @Test public void matchVocab_12() { test(null, null, node("U")); }

    @Test public void matchVocab_20() { test(node("NONE"), null, null); }
    @Test public void matchVocab_21() { test(null, null, node("NONE")); }

    @Test public void matchVocab_30() { test(null, ConstRDFS.rdfsDomain, null); }
    @Test public void matchVocab_31() { test(null, ConstRDFS.rdfsRange, null); }

    @Test public void matchVocab_40() { test(null, ConstRDFS.rdfsSubPropertyOf, node("T2")); }

    @Test public void matchVocab_99() { test(null, null, null); }


    private static PrintStream out = System.out;

    private void test(Node s, Node p, Node o) {
        String label = "find("+s+", "+p+", "+o+")";

        // The "right" answers (generated by Jena Inference Engine with rdfs-min.rules).
        List<Triple> expected = findInGraph(referenceGraph, s, p, o);
        // "match" under test.
        List<Triple> actual = match(s, p, o);
        boolean b = ListUtils.equalsUnordered(expected, actual);

        if ( ! b ) {
            out.println("Fail: "+label);
            LibTestRDFS.printDiff(out, expected, actual);
        }

        assertTrue(b, ()->label);
    }

    private List<Triple> match(Node s, Node p, Node o) {
        return matchVocab.match(s, p, o).toList();
    }
}
